package org.luxor.commons.storage.client.qcloud;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.model.*;
import com.qcloud.cos.region.Region;
import org.apache.commons.io.IOUtils;
import org.luxor.commons.core.utils.StrKit;
import org.luxor.commons.storage.client.AbstractStorageClient;
import org.luxor.commons.storage.client.AbstractStorageProperties;
import org.luxor.commons.storage.constant.StorageType;
import org.luxor.commons.storage.exception.StorageServiceException;
import org.luxor.commons.storage.exception.StorageTypeNotSupportedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.util.Date;


/**
 * 腾讯云 文件存储服务
 *
 * @author Mr.yan @date 2020/2/8
 */
public class QcloudStorageClient extends AbstractStorageClient {
    private static final Logger logger = LoggerFactory.getLogger(QcloudStorageClient.class);

    /**
     * 腾讯云 全局配置项
     */
    private QcloudProperties properties;

    private COSClient client;

    public QcloudStorageClient(QcloudProperties properties) {
        this.properties = properties;
        if (this.isEnabled()) {
            this.init();
        }
    }

    private void init() {
        logger.info("Initialization Qcloud open ( Running Qcloud Connector)");
        try {
            COSCredentials credentials = new BasicCOSCredentials(properties.getSecretId(), properties.getSecretKey());
            // 设置bucket所在的区域，华南：ap-guangzhou 西南：ap-chengdu 华东：ap-shanghai 华北：ap-beijing  香港:ap-hongkong
            Region region = new Region(properties.getRegion());
            ClientConfig clientConfig = new ClientConfig(region);
            client = new COSClient(credentials, clientConfig);

            // 初始化创建目录
            initPrefixDir(properties.getPrefix() + StrKit.SLASH);
            logger.info("Initialize Qcloud Connector Success,bye");
        } catch (Throwable e) {
            logger.error("Initialize Qcloud Connector Failure!", e);
            throw e;
        }
    }

    public void initPrefixDir(String prefixDir) {
        logger.info("Initialization Qcloud mkdir prefixDir. [{}]", prefixDir);
        try {
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(0);
            PutObjectRequest request = new PutObjectRequest(properties.getBucketName(), prefixDir, new ByteArrayInputStream(new byte[0]), metadata);
            client.putObject(request);
            logger.info("Initialization Qcloud mkdir prefixDir Success. ");
        } catch (Exception e) {
            logger.warn("初始化创建目录失败，请核对腾讯云配置信息", e);
            throw new StorageServiceException("初始化创建目录失败，请核对腾讯云配置信息", e);
        }
    }

    @Override
    public AbstractStorageProperties getConfig() {
        return this.properties;
    }

    @Override
    public boolean isEnabled() {
        return properties.isEnabled();
    }

    @Override
    public String upload(byte[] fileByte, String fileName, String suffix) {
        if (!this.isEnabled()) {
            logger.error("[未开启] 腾讯云文件存储功能");
            throw new StorageTypeNotSupportedException("[未开启] 腾讯云文件存储功能");
        }
        try {
            String fileFullPath = getFilePath(StorageType.QCLOUD, properties.getPrefix(), fileName, suffix);
            logger.info("上传文件,路径:{}", fileFullPath);

            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(fileByte.length);
            metadata.setLastModified(new Date());
            PutObjectRequest request = new PutObjectRequest(properties.getBucketName(), fileFullPath, new ByteArrayInputStream(fileByte), metadata);
            client.putObject(request);

            return fileFullPath;
        } catch (Exception e) {
            logger.error("上传文件失败，请核对腾讯云配置信息", e);
            throw new StorageServiceException("上传文件失败，请核对腾讯云配置信息", e);
        }
    }

    @Override
    public byte[] download(String fileFullPath) {
        if (!this.isEnabled()) {
            logger.error("[未开启] 腾讯云文件存储功能. fileFullPath:{}", fileFullPath);
            throw new StorageTypeNotSupportedException("[未开启] 腾讯云文件存储功能");
        }
        logger.info("下载文件,路径:{}", fileFullPath);

        COSObjectInputStream ois = null;
        try {
            GetObjectRequest getRequest = new GetObjectRequest(properties.getBucketName(), fileFullPath);
            COSObject object = client.getObject(getRequest);
            ois = object.getObjectContent();
            return IOUtils.toByteArray(ois);
        } catch (Exception e) {
            logger.error("下载文件失败，请核对腾讯云配置信息", e);
            throw new StorageServiceException("上传文件失败，请核对腾讯云配置信息", e);
        } finally {
            IOUtils.closeQuietly(ois);
        }
    }

    @Override
    public void delete(String fileFullPath) {
        if (!this.isEnabled()) {
            logger.error("[未开启] 腾讯云文件存储功能. fileFullPath:{}", fileFullPath);
            throw new StorageTypeNotSupportedException("[未开启] 腾讯云文件存储功能");
        }
        logger.info("删除文件,路径:{}", fileFullPath);

        try {
            DeleteObjectRequest request = new DeleteObjectRequest(properties.getBucketName(), fileFullPath);
            client.deleteObject(request);
        } catch (Exception e) {
            logger.error("删除文件失败，请核对腾讯云配置信息", e);
            throw new StorageServiceException("删除文件失败，请核对腾讯云配置信息", e);
        }
    }

}
